package com.cgnpc.scp.hse.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cgnpc.cud.boot.autoconfigure.aep.AepProperties;
import com.cgnpc.cud.core.domain.AjaxResult;
import com.cgnpc.cuddemo.utils.IDHelper;
import com.cgnpc.scp.common.bean.CreateFileInfo;
import com.cgnpc.scp.common.bean.MyPageResult;
import com.cgnpc.scp.common.exception.ScpException;
import com.cgnpc.scp.common.mybatis.entity.ScpCommonFileUpload;
import com.cgnpc.scp.common.mybatis.entity.ScpCommonSmsInfo;
import com.cgnpc.scp.common.pojo.UserInfo;
import com.cgnpc.scp.common.service.AppConstantService;
import com.cgnpc.scp.common.service.ExcelCustomTemplateService;
import com.cgnpc.scp.common.service.IScpCommonFileUploadService;
import com.cgnpc.scp.common.service.IScpCommonSmsInfoService;
import com.cgnpc.scp.common.service.RoleService;
import com.cgnpc.scp.common.utils.AjaxResultUtil;
import com.cgnpc.scp.common.utils.DataDictUtil;
import com.cgnpc.scp.common.utils.ListUtil;
import com.cgnpc.scp.common.utils.MyPageResultUtil;
import com.cgnpc.scp.common.utils.NumberUtil;
import com.cgnpc.scp.common.utils.SqlUtil;
import com.cgnpc.scp.common.utils.StringUtil;
import com.cgnpc.scp.hse.mybatis.entity.HseCheckOptionsConfig;
import com.cgnpc.scp.hse.mybatis.entity.HseCommonCheckOptionsConfig;
import com.cgnpc.scp.hse.mybatis.entity.HseMeetingFile;
import com.cgnpc.scp.hse.mybatis.entity.HseMeetingInfo;
import com.cgnpc.scp.hse.mybatis.entity.HseMeetingInfoExampleExtend;
import com.cgnpc.scp.hse.mybatis.entity.HseMeetingUser;
import com.cgnpc.scp.hse.mybatis.mapper.client.HseMeetingInfoMapper;
import com.cgnpc.scp.hse.mybatis.mapper.client.HseMeetingUserMapper;
import com.cgnpc.scp.hse.service.IHseCheckOptionsConfigService;
import com.cgnpc.scp.hse.service.IHseCommonCheckOptionsConfigService;
import com.cgnpc.scp.hse.service.IHseMeetingFileService;
import com.cgnpc.scp.hse.service.IHseMeetingInfoService;
import com.cgnpc.scp.hse.service.IHseMeetingUserService;
import com.cgnpc.scp.manager.mybatis.entity.DataDict;
import com.cgnpc.scp.manager.service.IDataDictService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.ibatis.session.SqlSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;

@Service
public class HseMeetingInfoServiceImpl implements IHseMeetingInfoService {
    private static final Logger LOGGER = LoggerFactory.getLogger(HseMeetingInfoServiceImpl.class);

    @Autowired
    private SqlSession sqlSession;

    @Autowired
    private MessageSource messageSource;

    @Autowired
    private AppConstantService appConstantService;

    @Autowired
    private HseMeetingInfoMapper hseMeetingInfoMapper;

    @Autowired
    private IHseMeetingUserService hseMeetingUserService;

    @Autowired
    private IHseMeetingFileService hseMeetingFileService;

    @Autowired
    private IHseCommonCheckOptionsConfigService hseCommonCheckOptionsConfigService;

    @Autowired
    private IHseCheckOptionsConfigService hseCheckOptionsConfigService;

    @Autowired
    private IScpCommonFileUploadService scpCommonFileUploadService;

    @Autowired
    private HseMeetingUserMapper hseMeetingUserMapper;

    @Autowired
    private AepProperties aepProperties;

    @Autowired
    private IScpCommonSmsInfoService scpCommonSmsInfoService;

    @Autowired
    private RoleService roleService;

    @Autowired
    private ExcelCustomTemplateService excelCustomTemplateService;

    @Autowired
    private IDataDictService dataDictService;

    /**
     * 创建查询Example
     *
     * @param loginUserInfo loginUserInfo
     * @param reqEntity     reqEntity
     * @param <T>           T
     * @return Example
     */
    private <T extends HseMeetingInfo> HseMeetingInfoExampleExtend createQueryExample(UserInfo loginUserInfo, T reqEntity) {
        String loginUserInfoUserId = loginUserInfo == null ? null : loginUserInfo.getUserId();

        HseMeetingInfoExampleExtend queryExample = new HseMeetingInfoExampleExtend();

        // 设置排序字段
        queryExample.setOrderByFieldList(reqEntity.getOrderByFieldList());

        // 设置查询条件

        // 试验内容
        if (!StringUtil.isNullOrSpace(reqEntity.getTrial())) {
            queryExample.setTrialLike(SqlUtil.valueJoinLikeBoth(reqEntity.getTrial()));
        }

        // 会议类型
        if (reqEntity.getMeetingType() != null) {
            queryExample.setMeetingTypeEqualTo(reqEntity.getMeetingType());
        }

        // 会议日期从
        if (reqEntity.getMeetingStartTimeFrom() != null) {
            queryExample.setMeetingStartTimeGreaterThanOrEqualTo(reqEntity.getMeetingStartTimeFrom());
        }

        // 会议日期至
        if (reqEntity.getMeetingStartTimeTo() != null) {
            queryExample.setMeetingStartTimeLessThanOrEqualTo(reqEntity.getMeetingStartTimeTo());
        }

        List<Integer> usedMeetingStatusList = new ArrayList<>();

        // 会议状态
        if (reqEntity.getMeetingStatus() != null) {
            usedMeetingStatusList.add(reqEntity.getMeetingStatus());
        }

        // 会议状态
        if (ListUtil.getListSizeWith0(reqEntity.getMeetingStatusList()) > 0) {
            usedMeetingStatusList.addAll(reqEntity.getMeetingStatusList());
        }

        if (ListUtil.getListSizeWith0(usedMeetingStatusList) > 0) {
            queryExample.setMeetingStatusIn(usedMeetingStatusList);
        }

        // hseadmin角色能查询所有数据，其他必须带上meetingUser值
        boolean hasRoleWithHseAdmin = roleService.hasRoleWithHseAdmin();

        // 与会人员工号
        if (hasRoleWithHseAdmin) {
            if (!StringUtil.isNullOrSpace(reqEntity.getMeetingUser())) {
                queryExample.setMeetingUserEqualsTo(reqEntity.getMeetingUser());
            }
        } else {
            if (StringUtil.isNullOrSpace(loginUserInfoUserId)) {
                queryExample.setMeetingUserIsNull(true);
            } else {
                queryExample.setMeetingUserEqualsTo(loginUserInfoUserId);
            }
        }

        return queryExample;
    }

    @Override
    public <T extends HseMeetingInfo> MyPageResult<T> loadByPaging(UserInfo loginUserInfo, T reqEntity) {
        // begin 分页查询
        // 第几页
        int pageNum = reqEntity.getPageNum();
        // 每页的数量
        int pageSize = reqEntity.getPageSize();
        // 创建Page对象，将pageNum，pageSize参数传入，必须位于数据库查询数据的语句之前，否则不生效
        com.github.pagehelper.Page<T> queryPage = PageHelper.startPage(pageNum, pageSize);

        // 创建queryExample
        HseMeetingInfoExampleExtend queryExample = createQueryExample(loginUserInfo, reqEntity);

        hseMeetingInfoMapper.selectByExampleWithCustom(queryExample);

        // pagehelper分页插件的问题，需要创建PageInfo才能获取总记录数，queryPage.getResult()和dbEntityList是一样的
        PageInfo<T> pageResult = new PageInfo<>(queryPage.getResult());

        // 创建分页结果集对象
        MyPageResult<T> myPageResult = MyPageResultUtil.createMyPageResult(pageResult);
        // end 分页查询

        return myPageResult;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public <T extends HseMeetingInfo> AjaxResult saveOrUpdate(UserInfo loginUserInfo, Locale reqLocale, List<T> reqEntityList) {
        final String logInfo = "[HseMeetingInfo_saveOrUpdate_UUID_" + UUID.randomUUID().toString() + "]";
        AjaxResult ajaxResult = null;
        final List<HseMeetingInfo> resultHseMeetingInfoList = new ArrayList<>();

        try {
            Date nowDate = new Date();
            // begin 获取登录用户的信息
            String loginUserInfoUserId = loginUserInfo.getUserId();
            String loginUserInfoUserName = loginUserInfo.getUserName();
            // end 获取登录用户的信息

            HseMeetingInfo usedEntity = null;
            HseMeetingInfo resultEntity = null;
            int saveRows = 0;
            int updateRows = 0;

            String reqId = null;
            List<HseMeetingUser> reqHseMeetingUserList = null;

            for (HseMeetingInfo reqEntity : reqEntityList) {
                reqId = reqEntity.getId();
                reqHseMeetingUserList = reqEntity.getHseMeetingUserList();
                reqHseMeetingUserList = reqHseMeetingUserList == null ? new ArrayList<>() : reqHseMeetingUserList;

                LOGGER.info("{}printInfo;HseMeetingInfo.id:{};"
                        , logInfo
                        , reqId
                );

                if (StringUtil.isNullOrSpace(reqId)) {
                    // 保存

                    usedEntity = new HseMeetingInfo();
                    // 设置主键
                    usedEntity.setId(IDHelper.uuidNew());
                    // trial 试验内容
                    usedEntity.setTrial(reqEntity.getTrial());
                    // team_name 班组名称
                    usedEntity.setTeamName(reqEntity.getTeamName());
                    // meeting_start_time 会议开始时间
                    usedEntity.setMeetingStartTime(reqEntity.getMeetingStartTime());
                    // meeting_end_time 会议结束时间
                    usedEntity.setMeetingEndTime(reqEntity.getMeetingEndTime());
                    // leading_user 负责人工号
                    usedEntity.setLeadingUser(reqEntity.getLeadingUser());
                    // leading_user_name 负责人姓名，例如：[P206992]张平
                    usedEntity.setLeadingUserName(reqEntity.getLeadingUserName());
                    // team_safety_user 班组安全员工号
                    usedEntity.setTeamSafetyUser(reqEntity.getTeamSafetyUser());
                    // team_safety_user_name 班组安全员姓名，例如：[P206992]张平
                    usedEntity.setTeamSafetyUserName(reqEntity.getTeamSafetyUserName());
                    // meeting_status 会议状态；值0未开始；1已完成；2已取消；
                    usedEntity.setMeetingStatus(reqEntity.getMeetingStatus());
                    // meeting_type 会议类型；值1班前会；2工前会；
                    usedEntity.setMeetingType(reqEntity.getMeetingType());
                    // trial_region 试验区域
                    usedEntity.setTrialRegion(reqEntity.getTrialRegion());
                    // system_code 系统代码
                    usedEntity.setSystemCode(reqEntity.getSystemCode());
                    // sms_notice 是否短信通知；值0不通知；1通知；
                    usedEntity.setSmsNotice(reqEntity.getSmsNotice());
                    // date_notice 是否添加日历；值0不加；1加；默认1；
                    usedEntity.setDateNotice(reqEntity.getDateNotice());

                    // begin 设置公共字段
                    // create_time 创建时间
                    usedEntity.setCreateTime(nowDate);
                    // create_user 创建人员工号
                    usedEntity.setCreateUser(loginUserInfoUserId);
                    // create_user_name 创建人姓名，例如：[P206992]张平
                    usedEntity.setCreateUserName(loginUserInfoUserName);
                    // last_update_time 更新时间
                    usedEntity.setLastUpdateTime(nowDate);
                    // last_update_user 更新人员工号
                    usedEntity.setLastUpdateUser(loginUserInfoUserId);
                    // last_update_user_name 更新人姓名，例如：[P206992]张平
                    usedEntity.setLastUpdateUserName(loginUserInfoUserName);
                    // end 设置公共字段

                    saveRows = hseMeetingInfoMapper.insert(usedEntity);

                    String usedMeetingInfoId = usedEntity.getId();

                    resultEntity = new HseMeetingInfo();
                    resultEntity.setId(usedEntity.getId());
                    resultEntity.setMessage("保存成功");
                    resultEntity.setSaveRows(saveRows);
                    resultHseMeetingInfoList.add(resultEntity);

                    // begin 创建安全人员信息
                    HseMeetingUser hseMeetingUserWithLeading = new HseMeetingUser();

                    hseMeetingUserWithLeading.setMeetingUserType(HseMeetingUser.MEETINGUSERTYPE_2_LEADING);
                    hseMeetingUserWithLeading.setMeetingUser(reqEntity.getLeadingUser());
                    hseMeetingUserWithLeading.setMeetingUserName(reqEntity.getLeadingUserName());
                    hseMeetingUserWithLeading.setSmsNotice(usedEntity.getSmsNotice());
                    // end 创建安全人员信息

                    // begin 创建班组安全员信息
                    HseMeetingUser hseMeetingUserWithTeamSafety = new HseMeetingUser();

                    hseMeetingUserWithTeamSafety.setMeetingUserType(HseMeetingUser.MEETINGUSERTYPE_3_TEAM_SAFETY);
                    hseMeetingUserWithTeamSafety.setMeetingUser(reqEntity.getTeamSafetyUser());
                    hseMeetingUserWithTeamSafety.setMeetingUserName(reqEntity.getTeamSafetyUserName());
                    hseMeetingUserWithTeamSafety.setSmsNotice(usedEntity.getSmsNotice());
                    // end 创建班组安全员信息

                    // begin 创建人信息
                    HseMeetingUser hseMeetingUserWithCreate = new HseMeetingUser();

                    hseMeetingUserWithCreate.setMeetingUserType(HseMeetingUser.MEETINGUSERTYPE_4_CREATE);
                    hseMeetingUserWithCreate.setMeetingUser(loginUserInfoUserId);
                    hseMeetingUserWithCreate.setMeetingUserName(loginUserInfoUserName);
                    hseMeetingUserWithCreate.setSmsNotice(usedEntity.getSmsNotice());
                    // end 创建人信息

                    // begin 保存或修改参会人员
                    reqHseMeetingUserList.add(hseMeetingUserWithLeading);
                    reqHseMeetingUserList.add(hseMeetingUserWithTeamSafety);
                    reqHseMeetingUserList.add(hseMeetingUserWithCreate);

                    for (HseMeetingUser reqHseMeetingUser : reqHseMeetingUserList) {
                        // 为每个人设置是否需要发送短信
                        if (reqHseMeetingUser.getSmsNotice() == null) {
                            reqHseMeetingUser.setSmsNotice(usedEntity.getSmsNotice());
                        }
                    }

                    hseMeetingUserService.saveOrUpdate(loginUserInfo, reqLocale, usedMeetingInfoId, reqHseMeetingUserList);
                    // end 保存或修改参会人员

                    // begin 保存检查项
                    List<HseCheckOptionsConfig> usedHseCheckOptionsConfigList = createHseCheckOptionsConfig(
                            loginUserInfo,
                            usedMeetingInfoId,
                            usedEntity.getMeetingType()
                    );

                    hseCheckOptionsConfigService.save(loginUserInfo, reqLocale, usedMeetingInfoId, usedHseCheckOptionsConfigList);
                    // end 保存检查项

                    // begin 保存Hse附件
                    List<HseMeetingFile> reqEntityHseMeetingFileList = reqEntity.getHseMeetingFileList();
                    List<HseMeetingFile> usedHseMeetingFileList = createHseMeetingFile(loginUserInfo, usedMeetingInfoId, reqEntityHseMeetingFileList);

                    hseMeetingFileService.save(loginUserInfo, reqLocale, usedHseMeetingFileList);
                    // end 保存Hse附件
                } else {
                    // 修改

                    // begin 校验登录用户能否操作会议
                    boolean checkCanOperateMeetingInfo = this.checkCanOperateMeetingInfo(logInfo, loginUserInfo, reqId);

                    if (!checkCanOperateMeetingInfo) {
                        LOGGER.error("{}无权限操作会议；checkCanOperateMeetingInfo:{};", logInfo, checkCanOperateMeetingInfo);
                        return AjaxResultUtil.createErrorMessage("无权限操作会议");
                    }
                    // end 校验登录用户能否操作会议

                    usedEntity = new HseMeetingInfo();
                    // 设置主键
                    usedEntity.setId(reqId);
                    // trial 试验内容
                    usedEntity.setTrial(reqEntity.getTrial());
                    // team_name 班组名称
                    usedEntity.setTeamName(reqEntity.getTeamName());
                    // meeting_start_time 会议开始时间
                    usedEntity.setMeetingStartTime(reqEntity.getMeetingStartTime());
                    // meeting_end_time 会议结束时间
                    usedEntity.setMeetingEndTime(reqEntity.getMeetingEndTime());
                    // leading_user 负责人工号
                    usedEntity.setLeadingUser(reqEntity.getLeadingUser());
                    // leading_user_name 负责人姓名，例如：[P206992]张平
                    usedEntity.setLeadingUserName(reqEntity.getLeadingUserName());
                    // team_safety_user 班组安全员工号
                    usedEntity.setTeamSafetyUser(reqEntity.getTeamSafetyUser());
                    // team_safety_user_name 班组安全员姓名，例如：[P206992]张平
                    usedEntity.setTeamSafetyUserName(reqEntity.getTeamSafetyUserName());
                    // meeting_status 会议状态；值0未开始；1已完成；2已取消；
                    usedEntity.setMeetingStatus(reqEntity.getMeetingStatus());
                    // meeting_type 会议类型；值1班前会；2工前会；
                    usedEntity.setMeetingType(reqEntity.getMeetingType());
                    // trial_region 试验区域
                    usedEntity.setTrialRegion(reqEntity.getTrialRegion());
                    // system_code 系统代码
                    usedEntity.setSystemCode(reqEntity.getSystemCode());
                    // sms_notice 是否短信通知；值0不通知；1通知；
                    usedEntity.setSmsNotice(reqEntity.getSmsNotice());
                    // date_notice 是否添加日历；值0不加；1加；默认1；
                    usedEntity.setDateNotice(reqEntity.getDateNotice());

                    // begin 设置公共字段
                    // create_time 创建时间
                    // usedEntity.setCreateTime(nowDate);
                    // create_user 创建人员工号
                    // usedEntity.setCreateUser(loginUserInfoUserId);
                    // create_user_name 创建人姓名，例如：[P206992]张平
                    // usedEntity.setCreateUserName(loginUserInfoUserName);
                    // last_update_time 更新时间
                    usedEntity.setLastUpdateTime(nowDate);
                    // last_update_user 更新人员工号
                    usedEntity.setLastUpdateUser(loginUserInfoUserId);
                    // last_update_user_name 更新人姓名，例如：[P206992]张平
                    usedEntity.setLastUpdateUserName(loginUserInfoUserName);
                    // end 设置公共字段

                    updateRows = hseMeetingInfoMapper.updateById(usedEntity);

                    resultEntity = new HseMeetingInfo();
                    resultEntity.setId(usedEntity.getId());
                    resultEntity.setMessage(updateRows <= 0 ? "修改失败" : "修改成功");
                    resultHseMeetingInfoList.add(resultEntity);

                    if (updateRows <= 0) {
                        continue;
                    }

                    String usedMeetingInfoId = usedEntity.getId();

                    // begin 创建安全人员信息
                    HseMeetingUser hseMeetingUserWithLeading = new HseMeetingUser();

                    hseMeetingUserWithLeading.setMeetingUserType(HseMeetingUser.MEETINGUSERTYPE_2_LEADING);
                    hseMeetingUserWithLeading.setMeetingUser(reqEntity.getLeadingUser());
                    hseMeetingUserWithLeading.setMeetingUserName(reqEntity.getLeadingUserName());
                    hseMeetingUserWithLeading.setSmsNotice(usedEntity.getSmsNotice());
                    // end 创建安全人员信息

                    // begin 创建班组安全员信息
                    HseMeetingUser hseMeetingUserWithTeamSafety = new HseMeetingUser();

                    hseMeetingUserWithTeamSafety.setMeetingUserType(HseMeetingUser.MEETINGUSERTYPE_3_TEAM_SAFETY);
                    hseMeetingUserWithTeamSafety.setMeetingUser(reqEntity.getTeamSafetyUser());
                    hseMeetingUserWithTeamSafety.setMeetingUserName(reqEntity.getTeamSafetyUserName());
                    hseMeetingUserWithTeamSafety.setSmsNotice(usedEntity.getSmsNotice());
                    // end 创建班组安全员信息

                    // begin 创建人信息
                    // HseMeetingUser hseMeetingUserWithCreate = new HseMeetingUser();

                    // hseMeetingUserWithCreate.setMeetingUserType(HseMeetingUser.MEETINGUSERTYPE6_4_CREATE);
                    // hseMeetingUserWithCreate.setMeetingUser(loginUserInfoUserId);
                    // hseMeetingUserWithCreate.setMeetingUserName(loginUserInfoUserName);
                    // hseMeetingUserWithCreate.setSmsNotice(usedEntity.getSmsNotice());
                    // end 创建人信息

                    reqHseMeetingUserList.add(hseMeetingUserWithLeading);
                    reqHseMeetingUserList.add(hseMeetingUserWithTeamSafety);
                    // 修改时不变更创建人信息
                    // reqHseMeetingUserList.add(hseMeetingUserWithCreate);

                    for (HseMeetingUser reqHseMeetingUser : reqHseMeetingUserList) {
                        // 为每个人设置是否需要发送短信
                        if (reqHseMeetingUser.getSmsNotice() == null) {
                            reqHseMeetingUser.setSmsNotice(usedEntity.getSmsNotice());
                        }
                    }

                    // 保存或修改参会人员
                    hseMeetingUserService.saveOrUpdate(loginUserInfo, reqLocale, usedMeetingInfoId, reqHseMeetingUserList);

                    // begin 修改Hse附件
                    List<HseMeetingFile> reqEntityHseMeetingFileList = reqEntity.getHseMeetingFileList();
                    hseMeetingFileService.updateWithMeetingInfoUpdate(loginUserInfo, reqLocale, usedMeetingInfoId, reqEntityHseMeetingFileList);
                    // end 修改Hse附件
                }
            }

            ajaxResult = AjaxResultUtil.createI18nSuccessDefaultMessage(reqLocale, messageSource, resultHseMeetingInfoList);
        } catch (Exception e) {
            LOGGER.error("{}error;", logInfo, e);
            throw e;
        }

        return ajaxResult;
    }

    @Override
    public <T extends HseMeetingInfo> CreateFileInfo exportExcel(UserInfo loginUserInfo, T reqEntity) throws Exception {
        final String logInfo = "[exportExcel_UUID_" + UUID.randomUUID() + "]";
        CreateFileInfo createFileInfo = null;

        try {
            // 创建queryExample
            HseMeetingInfoExampleExtend queryExample = createQueryExample(loginUserInfo, reqEntity);

            // mappedStatementNamespace为mybatis生成的mapper.xml中的命名空间
            String mappedStatementNamespace = "com.cgnpc.scp.hse.mybatis.mapper.client.HseMeetingInfoMapper";
            // mappedStatementMethod为mybatis生成的mapper.xml中的方法
            String mappedStatementMethod = "selectByExampleWithCustom";
            // mappedStatementId为具体指向的方法
            String mappedStatementId = mappedStatementNamespace + "." + mappedStatementMethod;

            // mappedStatementParameter可以为mybatis自动生成的XxxExample实体类，例如UserExample
            Object mappedStatementParameter = queryExample;
            String exportDictGroupKey = DataDictUtil.DICT_GROUP_KEY_WITH_HSEMEETINGINFO_EXPORTEXCEL;

            createFileInfo = excelCustomTemplateService.createXlsxToWebDir(
                    sqlSession
                    , mappedStatementId
                    , mappedStatementParameter
                    , exportDictGroupKey
            );
        } catch (Exception e) {
            LOGGER.error("{}error;", logInfo, e);
            throw e;
        }

        return createFileInfo;
    }

    @Override
    public <T extends HseMeetingInfo> T queryById(T reqEntity) {
        String reqId = reqEntity.getId();

        if (StringUtil.isNullOrSpace(reqId)) {
            return null;
        }

        T dbEntity = (T) hseMeetingInfoMapper.selectById(reqId);

        if (dbEntity == null) {
            return dbEntity;
        }

        String dbEntityId = dbEntity.getId();

        List<HseMeetingUser> dbHseMeetingUserList = hseMeetingUserService.queryByMeetingInfoId(dbEntityId);
        List<HseMeetingUser> dbHseMeetingUserShowList = hseMeetingUserService.queryByMeetingInfoIdShow(dbEntityId);
        List<HseMeetingFile> dbHseMeetingFileList = hseMeetingFileService.queryByMeetingInfoId(dbEntityId);
        List<HseCheckOptionsConfig> dbHseCheckOptionsConfigTreeList = hseCheckOptionsConfigService.queryTreeByMeetingInfoId(dbEntityId);

        dbEntity.setHseMeetingUserList(dbHseMeetingUserList);
        dbEntity.setHseMeetingUserShowList(dbHseMeetingUserShowList);
        dbEntity.setHseMeetingFileList(dbHseMeetingFileList);
        dbEntity.setHseCheckOptionsConfigTreeList(dbHseCheckOptionsConfigTreeList);

        return dbEntity;
    }

    @Override
    public <T extends HseMeetingInfo> T queryByIdOnlyInfo(String id) {
        if (StringUtil.isNullOrSpace(id)) {
            return null;
        }

        return (T) hseMeetingInfoMapper.selectById(id);
    }

    @Override
    public <T extends HseMeetingInfo> List<T> queryByIdOnlyInfo(List<String> idList) {
        if (ListUtil.getListSizeWith0(idList) <= 0) {
            return null;
        }

        return (List<T>) hseMeetingInfoMapper.selectBatchIds(idList);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public <T extends HseMeetingInfo> AjaxResult deleteById(UserInfo loginUserInfo, Locale reqLocale, T reqEntity) {
        final String logInfo = "[HseMeetingInfo_deleteById_UUID_" + UUID.randomUUID().toString() + "]";
        AjaxResult ajaxResult = null;

        try {
            List<String> reqIds = reqEntity.getIds();

            if (ListUtil.getListSizeWith0(reqIds) <= 0) {
                return AjaxResultUtil.createErrorMessage("请求参数不正确", null);
            }

            LOGGER.info("{}reqIds:{};"
                    , logInfo
                    , reqIds
            );

            // begin 校验登录用户能否操作会议
            for (String reqId : reqIds) {
                boolean checkCanOperateMeetingInfo = this.checkCanOperateMeetingInfo(logInfo, loginUserInfo, reqId);

                if (!checkCanOperateMeetingInfo) {
                    LOGGER.error("{}无权限操作会议；checkCanOperateMeetingInfo:{};", logInfo, checkCanOperateMeetingInfo);
                    return AjaxResultUtil.createErrorMessage("无权限操作会议");
                }
            }
            // end 校验登录用户能否操作会议

            int delRows = hseMeetingInfoMapper.deleteBatchIds(reqIds);

            hseMeetingUserService.deleteById(reqIds);
            hseMeetingFileService.deleteById(reqIds);
            hseCheckOptionsConfigService.deleteById(reqIds);

            ajaxResult = AjaxResultUtil.createSuccessMessage("删除成功，共删除" + delRows + "行记录；", delRows);
        } catch (Exception e) {
            LOGGER.error("{}error;", logInfo, e);
            throw e;
        }

        return ajaxResult;
    }

    /**
     * 创建检查项
     *
     * @param loginUserInfo     登录人
     * @param usedMeetingInfoId 会议id
     * @param meetingType       会议类型
     * @return 检查项
     */
    private List<HseCheckOptionsConfig> createHseCheckOptionsConfig(
            UserInfo loginUserInfo,
            String usedMeetingInfoId
            , Integer meetingType
    ) {
        Date nowDate = new Date();
        // begin 获取登录用户的信息
        String loginUserInfoUserId = loginUserInfo.getUserId();
        String loginUserInfoUserName = loginUserInfo.getUserName();
        // end 获取登录用户的信息

        // 查询公共的检查选项
        List<HseCommonCheckOptionsConfig> dbOptionList = hseCommonCheckOptionsConfigService.loadListByMeetingType(meetingType);

        // begin 创建检查项
        List<HseCheckOptionsConfig> usedHseCheckOptionsConfigList = new ArrayList<>();

        if (ListUtil.getListSizeWith0(dbOptionList) > 0) {
            HseCheckOptionsConfig hseCheckOptionsConfig = null;

            Map<String, HseCheckOptionsConfig> commonConfigIdWithObjectMap = new HashMap<>();

            for (HseCommonCheckOptionsConfig dbOption : dbOptionList) {
                hseCheckOptionsConfig = new HseCheckOptionsConfig();
                hseCheckOptionsConfig.setId(IDHelper.uuidNew());
                hseCheckOptionsConfig.setParentId(null); // 需要设定parentId
                hseCheckOptionsConfig.setMeetingInfoId(usedMeetingInfoId);
                hseCheckOptionsConfig.setCommonConfigId(dbOption.getId());
                hseCheckOptionsConfig.setCommonConfigParentId(dbOption.getParentId());
                hseCheckOptionsConfig.setOrderIndex(dbOption.getOrderIndex());
                hseCheckOptionsConfig.setOptionText(dbOption.getOptionText());
                hseCheckOptionsConfig.setOptionTextEn(dbOption.getOptionTextEn());
                hseCheckOptionsConfig.setCreateTime(nowDate);
                hseCheckOptionsConfig.setCreateUser(loginUserInfoUserId);
                hseCheckOptionsConfig.setCreateUserName(loginUserInfoUserName);
                hseCheckOptionsConfig.setLastUpdateTime(nowDate);
                hseCheckOptionsConfig.setLastUpdateUser(loginUserInfoUserId);
                hseCheckOptionsConfig.setLastUpdateUserName(loginUserInfoUserName);
                hseCheckOptionsConfig.setInspectionTime(null);
                hseCheckOptionsConfig.setInspectionUser(null);
                hseCheckOptionsConfig.setInspectionUserName(null);
                hseCheckOptionsConfig.setOptionValue(dbOption.getOptionValue());
                hseCheckOptionsConfig.setNeedInspection(dbOption.getNeedInspection());
                hseCheckOptionsConfig.setIsInspection(HseCheckOptionsConfig.ISINSPECTION_N);

                usedHseCheckOptionsConfigList.add(hseCheckOptionsConfig);
                commonConfigIdWithObjectMap.put(dbOption.getId(), hseCheckOptionsConfig);
            }

            String usedCommonConfigParentId = null;
            String usedConfigParentId = null;
            HseCheckOptionsConfig usedConfigParent = null;

            for (HseCheckOptionsConfig usedHseCheckOptionsConfig : usedHseCheckOptionsConfigList) {
                usedCommonConfigParentId = usedHseCheckOptionsConfig.getCommonConfigParentId();

                usedConfigParent = commonConfigIdWithObjectMap.get(usedCommonConfigParentId);

                usedConfigParentId = usedConfigParent == null ? HseCheckOptionsConfig.PARENTID_ROOT : usedConfigParent.getId();
                usedHseCheckOptionsConfig.setParentId(usedConfigParentId);
            }
        }
        // end 创建检查项

        return usedHseCheckOptionsConfigList;
    }

    @Override
    public <T extends HseMeetingInfo> List<T> queryNeedStartList(final int pageNum, final int pageSize) {
        // 查询 开始时间 >= 现在时间 - 5分钟
        Date nowDate = new Date();
        Calendar calendar = Calendar.getInstance();

        calendar.setTime(nowDate);
        calendar.add(Calendar.MINUTE, 5);
        Date startTimeEnd = calendar.getTime();

        // 创建Page对象
        IPage<HseMeetingInfo> queryPage = new Page<>();
        queryPage.setCurrent(pageNum);
        queryPage.setSize(pageSize);

        // 创建查询条件
        QueryWrapper<HseMeetingInfo> queryWrapper = new QueryWrapper<>();

        queryWrapper.orderByAsc("id");

        queryWrapper.eq("meeting_status", HseMeetingInfo.MEETINGSTATUS_0);
        // addCriterion("meeting_start_time <=", value, "meetingStartTime");
        queryWrapper.lt("meeting_start_time", startTimeEnd);

        IPage<HseMeetingInfo> pageResult = hseMeetingInfoMapper.selectPage(queryPage, queryWrapper);

        return (List<T>) pageResult.getRecords();
    }

    @Override
    public <T extends HseMeetingInfo> List<T> queryNeedEndList(int pageNum, int pageSize) {
        // 查询 结束时间 <= 当前时间 - 10分钟
        Date nowDate = new Date();
        Calendar calendar = Calendar.getInstance();

        calendar.setTime(nowDate);
        calendar.add(Calendar.MINUTE, -10);
        Date endTime = calendar.getTime();

        // 创建Page对象
        IPage<HseMeetingInfo> queryPage = new Page<>();
        queryPage.setCurrent(pageNum);
        queryPage.setSize(pageSize);

        // 创建查询条件
        QueryWrapper<HseMeetingInfo> queryWrapper = new QueryWrapper<>();

        queryWrapper.orderByAsc("id");

        // MEETINGSTATUS_3进行中状态
        queryWrapper.eq("meeting_status", HseMeetingInfo.MEETINGSTATUS_3);
        // addCriterion("meeting_end_time <=", value, "meetingEndTime");
        queryWrapper.lt("meeting_end_time", endTime);

        IPage<HseMeetingInfo> pageResult = hseMeetingInfoMapper.selectPage(queryPage, queryWrapper);

        return (List<T>) pageResult.getRecords();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult startMeetingInfo(UserInfo loginUserInfo, Locale reqLocale, String id) throws Exception {
        final boolean timerAutoRun = false;
        return this.startMeetingInfo(loginUserInfo, reqLocale, id, timerAutoRun);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult startMeetingInfo(UserInfo loginUserInfo, Locale reqLocale, String id, boolean timerAutoRun) throws Exception {
        final String logInfo = "[startMeetingInfo_UUID_" + UUID.randomUUID().toString() + "]";

        try {
            LOGGER.info("{}printInfo;meetingInfoId:{};"
                    , logInfo
                    , id
            );

            if (StringUtil.isNullOrSpace(id)) {
                LOGGER.error("{}id is null or space;", logInfo);
                String i18nKey = "message.scp.id.is.not.null.or.space";
                return AjaxResultUtil.createI18nErrorMessage(reqLocale, messageSource, i18nKey);
            }

//            // begin 获取登录用户的信息
//            // 某些特殊情况需要使用，例如有定时器自动运行无法获取到用户信息
//            String loginUserInfoUserId = null;
//            String loginUserInfoUserName = null;
//
//            if (loginUserInfo != null) {
//                loginUserInfoUserId = loginUserInfo.getUserId();
//                loginUserInfoUserName = loginUserInfo.getUserName();
//            }
//            // end 获取登录用户的信息

            // begin 校验登录用户能否操作会议
            if (!timerAutoRun) {
                boolean checkCanOperateMeetingInfo = this.checkCanOperateMeetingInfo(logInfo, loginUserInfo, id);

                if (!checkCanOperateMeetingInfo) {
                    LOGGER.error("{}无权限操作会议；checkCanOperateMeetingInfo:{};", logInfo, checkCanOperateMeetingInfo);
                    return AjaxResultUtil.createErrorMessage("无权限操作会议");
                }
            }
            // end 校验登录用户能否操作会议

            HseMeetingInfo dbHseMeetingInfo = hseMeetingInfoMapper.selectById(id);

            if (dbHseMeetingInfo == null) {
                LOGGER.error("{}会议不存在", logInfo);
                String i18nKey = "message.scp.hseMeetingInfo.notExists";
                return AjaxResultUtil.createI18nErrorMessage(reqLocale, messageSource, i18nKey);
            }

            Integer dbMeetingStatus = dbHseMeetingInfo.getMeetingStatus();

            if (dbMeetingStatus == null || dbMeetingStatus != HseMeetingInfo.MEETINGSTATUS_0) {
                // 只有未开始的会议才能执行开始操作
                LOGGER.error("{}只有未开始的会议才能执行开始操作", logInfo);
                String i18nKey = "message.scp.hseMeetingInfo.startMeeting.meetingStatus.need.0";
                return AjaxResultUtil.createI18nErrorMessage(reqLocale, messageSource, i18nKey);
            }

            Date nowDate = new Date();

            HseMeetingInfo usedInfo = new HseMeetingInfo();
            usedInfo.setId(id);
            usedInfo.setMeetingStatus(HseMeetingInfo.MEETINGSTATUS_3);
            usedInfo.setRealStartTime(nowDate);

            int updateRows = hseMeetingInfoMapper.updateById(usedInfo);
            LOGGER.info("{}update.to.MEETINGSTATUS_3;updateRows:{};", logInfo, updateRows);

            if (updateRows <= 0) {
                LOGGER.error("{}updateRows <= 0;", logInfo);
                // 没有更新会议信息
                String i18nKey = "message.scp.hseMeetingInfo.update.rows.lessThanOrEquals.0";
                return AjaxResultUtil.createI18nErrorMessage(reqLocale, messageSource, i18nKey);
            } else if (updateRows > 1) {
                LOGGER.error("{}updateRows > 1;更新了多条会议记录", logInfo);
                String i18nKey = "message.scp.hseMeetingInfo.update.rows.greaterThan.1";
                String i18nMessage = messageSource.getMessage(i18nKey, null, reqLocale);
                throw new ScpException(i18nMessage);
            }

            String i18nKey = "message.scp.hseMeetingInfo.startMeetingInfo.success";
            return AjaxResultUtil.createI18nSuccessMessage(reqLocale, messageSource, i18nKey);
        } catch (ScpException escp) {
            LOGGER.error("{}error;", logInfo, escp);
            throw escp;
        } catch (Exception e) {
            LOGGER.error("{}error;", logInfo, e);
            throw e;
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult endMeetingInfo(UserInfo loginUserInfo, Locale reqLocale, String id) throws Exception {
        final boolean timerAutoRun = false;
        return this.endMeetingInfo(loginUserInfo, reqLocale, id, timerAutoRun);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult endMeetingInfo(UserInfo loginUserInfo, Locale reqLocale, String id, boolean timerAutoRun) throws Exception {
        final String logInfo = "[endMeetingInfo_UUID_" + UUID.randomUUID().toString() + "]";

        try {
            LOGGER.info("{}printInfo;meetingInfoId:{};"
                            + "timerAutoRun:{};"
                    , logInfo
                    , id
                    , timerAutoRun
            );

            if (StringUtil.isNullOrSpace(id)) {
                LOGGER.error("{}id is null or space;", logInfo);
                String i18nKey = "message.scp.id.is.not.null.or.space";
                return AjaxResultUtil.createI18nErrorMessage(reqLocale, messageSource, i18nKey);
            }

//            // begin 获取登录用户的信息
//            // 某些特殊情况需要使用，例如有定时器自动运行无法获取到用户信息
//            String loginUserInfoUserId = null;
//            String loginUserInfoUserName = null;
//
//            if (loginUserInfo != null) {
//                loginUserInfoUserId = loginUserInfo.getUserId();
//                loginUserInfoUserName = loginUserInfo.getUserName();
//            }
//            // end 获取登录用户的信息

            // begin 校验登录用户能否操作会议
            // 如果定时器自动运行则不校验登录人信息
            if (!timerAutoRun) {
                boolean checkCanOperateMeetingInfo = this.checkCanOperateMeetingInfo(logInfo, loginUserInfo, id);

                if (!checkCanOperateMeetingInfo) {
                    LOGGER.error("{}无权限操作会议；checkCanOperateMeetingInfo:{};", logInfo, checkCanOperateMeetingInfo);
                    return AjaxResultUtil.createErrorMessage("无权限操作会议");
                }
            }
            // end 校验登录用户能否操作会议

            HseMeetingInfo dbHseMeetingInfo = hseMeetingInfoMapper.selectById(id);

            if (dbHseMeetingInfo == null) {
                LOGGER.error("{}会议不存在", logInfo);
                String i18nKey = "message.scp.hseMeetingInfo.notExists";
                return AjaxResultUtil.createI18nErrorMessage(reqLocale, messageSource, i18nKey);
            }

            Integer dbMeetingStatus = dbHseMeetingInfo.getMeetingStatus();

            if (dbMeetingStatus == null || dbMeetingStatus != HseMeetingInfo.MEETINGSTATUS_3) {
                // 只有进行中的会议才能执行结束操作
                LOGGER.error("{}只有进行中的会议才能执行结束操作", logInfo);
                String i18nKey = "message.scp.hseMeetingInfo.endMeeting.need.running";
                return AjaxResultUtil.createI18nErrorMessage(reqLocale, messageSource, i18nKey);
            }

            Date nowDate = new Date();

            HseMeetingInfo usedInfo = new HseMeetingInfo();
            usedInfo.setId(id);
            usedInfo.setMeetingStatus(HseMeetingInfo.MEETINGSTATUS_1);
            usedInfo.setRealEndTime(nowDate);

            int updateRows = hseMeetingInfoMapper.updateById(usedInfo);
            LOGGER.info("{}update.to.MEETINGSTATUS_1;updateRows:{};", logInfo, updateRows);

            if (updateRows <= 0) {
                LOGGER.error("{}updateRows <= 0;", logInfo);
                // 没有更新会议信息
                String i18nKey = "message.scp.hseMeetingInfo.update.rows.lessThanOrEquals.0";
                return AjaxResultUtil.createI18nErrorMessage(reqLocale, messageSource, i18nKey);
            } else if (updateRows > 1) {
                LOGGER.error("{}updateRows > 1;更新了多条会议记录", logInfo);
                String i18nKey = "message.scp.hseMeetingInfo.update.rows.greaterThan.1";
                String i18nMessage = messageSource.getMessage(i18nKey, null, reqLocale);
                throw new ScpException(i18nMessage);
            }

            // Hse会议结束成功
            String i18nKey = "message.scp.hseMeetingInfo.endMeetingInfo.success";
            return AjaxResultUtil.createI18nSuccessMessage(reqLocale, messageSource, i18nKey);
        } catch (ScpException escp) {
            LOGGER.error("{}error;", logInfo, escp);
            throw escp;
        } catch (Exception e) {
            LOGGER.error("{}error;", logInfo, e);
            throw e;
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult cancelMeetingInfo(UserInfo loginUserInfo, Locale reqLocale, String id) throws Exception {
        final String logInfo = "[cancelMeetingInfo_UUID_" + UUID.randomUUID().toString() + "]";

        try {
            LOGGER.info("{}printInfo;meetingInfoId:{};"
                    , logInfo
                    , id
            );

            if (StringUtil.isNullOrSpace(id)) {
                LOGGER.error("{}id is null or space;", logInfo);
                String i18nKey = "message.scp.id.is.not.null.or.space";
                return AjaxResultUtil.createI18nErrorMessage(reqLocale, messageSource, i18nKey);
            }

//            // begin 获取登录用户的信息
//            // 某些特殊情况需要使用，例如有定时器自动运行无法获取到用户信息
//            String loginUserInfoUserId = null;
//            String loginUserInfoUserName = null;
//
//            if (loginUserInfo != null) {
//                loginUserInfoUserId = loginUserInfo.getUserId();
//                loginUserInfoUserName = loginUserInfo.getUserName();
//            }
//            // end 获取登录用户的信息

            // begin 校验登录用户能否操作会议
            boolean checkCanOperateMeetingInfo = this.checkCanOperateMeetingInfo(logInfo, loginUserInfo, id);

            if (!checkCanOperateMeetingInfo) {
                LOGGER.error("{}无权限操作会议；checkCanOperateMeetingInfo:{};", logInfo, checkCanOperateMeetingInfo);
                return AjaxResultUtil.createErrorMessage("无权限操作会议");
            }
            // end 校验登录用户能否操作会议

            HseMeetingInfo dbHseMeetingInfo = hseMeetingInfoMapper.selectById(id);

            if (dbHseMeetingInfo == null) {
                LOGGER.error("{}会议不存在", logInfo);
                String i18nKey = "message.scp.hseMeetingInfo.notExists";
                return AjaxResultUtil.createI18nErrorMessage(reqLocale, messageSource, i18nKey);
            }

            Integer dbMeetingStatus = dbHseMeetingInfo.getMeetingStatus();

            if (dbMeetingStatus == null || dbMeetingStatus != HseMeetingInfo.MEETINGSTATUS_0) {
                // 只有未开始的会议才能执行取消操作
                LOGGER.error("{}只有未开始的会议才能执行取消操作", logInfo);
                String i18nKey = "message.scp.hseMeetingInfo.cancelMeeting.meetingStatus.need.0";
                return AjaxResultUtil.createI18nErrorMessage(reqLocale, messageSource, i18nKey);
            }

            HseMeetingInfo usedInfo = new HseMeetingInfo();
            usedInfo.setId(id);
            usedInfo.setMeetingStatus(HseMeetingInfo.MEETINGSTATUS_2);

            int updateRows = hseMeetingInfoMapper.updateById(usedInfo);
            LOGGER.info("{}update.to.MEETINGSTATUS_2;updateRows:{};", logInfo, updateRows);

            if (updateRows <= 0) {
                LOGGER.error("{}updateRows <= 0;", logInfo);
                // 没有更新会议信息
                String i18nKey = "message.scp.hseMeetingInfo.update.rows.lessThanOrEquals.0";
                return AjaxResultUtil.createI18nErrorMessage(reqLocale, messageSource, i18nKey);
            } else if (updateRows > 1) {
                LOGGER.error("{}updateRows > 1;更新了多条会议记录", logInfo);
                String i18nKey = "message.scp.hseMeetingInfo.update.rows.greaterThan.1";
                String i18nMessage = messageSource.getMessage(i18nKey, null, reqLocale);
                throw new ScpException(i18nMessage);
            }

            // Hse会议取消成功
            String i18nKey = "message.scp.hseMeetingInfo.cancelMeetingInfo.success";
            return AjaxResultUtil.createI18nSuccessMessage(reqLocale, messageSource, i18nKey);
        } catch (ScpException escp) {
            LOGGER.error("{}error;", logInfo, escp);
            throw escp;
        } catch (Exception e) {
            LOGGER.error("{}error;", logInfo, e);
            throw e;
        }
    }

    /**
     * 创建附件信息
     *
     * @param loginUserInfo         登录人信息
     * @param usedMeetingInfoId     Hse会议id
     * @param reqHseMeetingFileList 上传附件的信息
     * @return 补充数据之后的附件信息
     */
    private List<HseMeetingFile> createHseMeetingFile(
            UserInfo loginUserInfo
            , String usedMeetingInfoId
            , List<HseMeetingFile> reqHseMeetingFileList
    ) {
//        Date nowDate = new Date();
//        // begin 获取登录用户的信息
//        String loginUserInfoUserId = loginUserInfo.getUserId();
//        String loginUserInfoUserName = loginUserInfo.getUserName();
//        // end 获取登录用户的信息

        if (ListUtil.getListSizeWith0(reqHseMeetingFileList) <= 0) {
            return null;
        }

        List<HseMeetingFile> usedHseMeetingFileList = new ArrayList<>();
        HseMeetingFile usedHseMeetingFile = null;
        String reqScpCommonFileUploadId = null;
        Integer reqMeetingFileType = null;

        List<String> reqScpCommonFileUploadIdListWithDoc = new ArrayList<>();
        List<String> reqScpCommonFileUploadIdListWithAudio = new ArrayList<>();

        for (HseMeetingFile reqHseMeetingFile : reqHseMeetingFileList) {
            reqScpCommonFileUploadId = reqHseMeetingFile.getScpCommonFileUploadId();
            reqMeetingFileType = reqHseMeetingFile.getMeetingFileType();

            if (StringUtil.isNullOrSpace(reqScpCommonFileUploadId)) {
                LOGGER.error("reqMeetingFileType is null or space");
                throw new ScpException("reqMeetingFileType is null or space");
            }

            if (reqMeetingFileType == null) {
                LOGGER.error("reqMeetingFileType is null");
                throw new ScpException("reqMeetingFileType is null");
            }

            if (reqMeetingFileType == HseMeetingFile.MEETINGFILETYPE_1_DOC) {
                // 文档类型
                reqScpCommonFileUploadIdListWithDoc.add(reqScpCommonFileUploadId);
            } else if (reqMeetingFileType == HseMeetingFile.MEETINGFILETYPE_2_AUDIO) {
                reqScpCommonFileUploadIdListWithAudio.add(reqScpCommonFileUploadId);
            }
        }

        // 创建文档信息
        if (ListUtil.getListSizeWith0(reqScpCommonFileUploadIdListWithDoc) > 0) {
            List<ScpCommonFileUpload> dbScpCommonFileUploadList = scpCommonFileUploadService.loadById(reqScpCommonFileUploadIdListWithDoc);

            if (ListUtil.getListSizeWith0(dbScpCommonFileUploadList) != ListUtil.getListSizeWith0(reqScpCommonFileUploadIdListWithDoc)) {
                LOGGER.error("upload file not exists");
                throw new ScpException("upload file not exists");
            }

            for (ScpCommonFileUpload dbScpCommonFileUpload : dbScpCommonFileUploadList) {
                usedHseMeetingFile = new HseMeetingFile();
                usedHseMeetingFileList.add(usedHseMeetingFile);

                fillHseMeetingFile(usedHseMeetingFile, dbScpCommonFileUpload);

                usedHseMeetingFile.setId(IDHelper.uuidNew());
                usedHseMeetingFile.setMeetingInfoId(usedMeetingInfoId);
                usedHseMeetingFile.setMeetingFileType(HseMeetingFile.MEETINGFILETYPE_1_DOC);
            }
        }

        // 创建录音信息
        if (ListUtil.getListSizeWith0(reqScpCommonFileUploadIdListWithAudio) > 0) {
            List<ScpCommonFileUpload> dbScpCommonFileUploadList = scpCommonFileUploadService.loadById(reqScpCommonFileUploadIdListWithAudio);

            if (ListUtil.getListSizeWith0(dbScpCommonFileUploadList) != ListUtil.getListSizeWith0(reqScpCommonFileUploadIdListWithAudio)) {
                LOGGER.error("upload file not exists");
                throw new ScpException("upload file not exists");
            }

            for (ScpCommonFileUpload dbScpCommonFileUpload : dbScpCommonFileUploadList) {
                usedHseMeetingFile = new HseMeetingFile();
                usedHseMeetingFileList.add(usedHseMeetingFile);

                fillHseMeetingFile(usedHseMeetingFile, dbScpCommonFileUpload);

                usedHseMeetingFile.setId(IDHelper.uuidNew());
                usedHseMeetingFile.setMeetingInfoId(usedMeetingInfoId);
                usedHseMeetingFile.setMeetingFileType(HseMeetingFile.MEETINGFILETYPE_2_AUDIO);
            }
        }

        return usedHseMeetingFileList;
    }

    public void fillHseMeetingFile(HseMeetingFile usedHseMeetingFile, ScpCommonFileUpload scpCommonFileUpload) {
        usedHseMeetingFile.setFileType(scpCommonFileUpload.getFileCenterFileType());
        usedHseMeetingFile.setFileOriginalName(scpCommonFileUpload.getFileCenterFileName());
        usedHseMeetingFile.setFileName(scpCommonFileUpload.getFileCenterFileName());
        usedHseMeetingFile.setFileSizeByte(scpCommonFileUpload.getFileCenterFileSize());
        usedHseMeetingFile.setFilePath(null);
        usedHseMeetingFile.setFileWebPath(scpCommonFileUpload.getFileCenterUrl());
        usedHseMeetingFile.setCreateTime(scpCommonFileUpload.getCreateTime());
        usedHseMeetingFile.setCreateUser(scpCommonFileUpload.getCreateUser());
        usedHseMeetingFile.setCreateUserName(scpCommonFileUpload.getCreateUserName());
        usedHseMeetingFile.setLastUpdateTime(scpCommonFileUpload.getLastUpdateTime());
        usedHseMeetingFile.setLastUpdateUser(scpCommonFileUpload.getLastUpdateUser());
        usedHseMeetingFile.setLastUpdateUserName(scpCommonFileUpload.getLastUpdateUserName());
        usedHseMeetingFile.setFileCenterTenantId(scpCommonFileUpload.getFileCenterTenantId());
        usedHseMeetingFile.setFileCenterAppId(scpCommonFileUpload.getFileCenterAppId());
        usedHseMeetingFile.setFileCenterAppName(scpCommonFileUpload.getFileCenterAppName());
        usedHseMeetingFile.setFileCenterFileId(scpCommonFileUpload.getFileCenterFileId());
        usedHseMeetingFile.setFileCenterFileSize(scpCommonFileUpload.getFileCenterFileSize());
        usedHseMeetingFile.setFileCenterUrl(scpCommonFileUpload.getFileCenterUrl());
        usedHseMeetingFile.setScpCommonFileUploadId(scpCommonFileUpload.getId());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ScpCommonSmsInfo sendSmsMessage(String reqHseMeetingInfoId) {
        final String logInfo = "[sendSmsMessage_UUID_" + UUID.randomUUID().toString() + "]";

        try {
            if (StringUtil.isNullOrSpace(reqHseMeetingInfoId)) {
                return null;
            }

            // begin 查询短信是否需要发送
            QueryWrapper<HseMeetingUser> queryWrapperWithHseMeetingUser = new QueryWrapper<>();

            queryWrapperWithHseMeetingUser.eq("meeting_info_id", reqHseMeetingInfoId);
            queryWrapperWithHseMeetingUser.eq("sms_notice", HseMeetingUser.SMSNOTICE_1);
            queryWrapperWithHseMeetingUser.eq("sms_send_status", HseMeetingUser.SMSSENDSTATUS_0);

            List<HseMeetingUser> dbHseMeetingUserList = hseMeetingUserMapper.selectList(queryWrapperWithHseMeetingUser);
            int dbHseMeetingUserListSize = ListUtil.getListSizeWith0(dbHseMeetingUserList);

            if (dbHseMeetingUserListSize <= 0) {
                return null;
            }
            // end 查询短信是否需要发送

            // begin 查询数据字典信息
            List<DataDict> dbDataDictList = dataDictService.queryByDictGroupKey(Arrays.asList(DataDictUtil.DICT_GROUP_KEY_WITH_HSEMEETINGINFO_MEETING_TYPE));
            Map<String, Map<String, DataDict>> usedDictGroupKeyWithDictKeyWithMap = DataDictUtil.parseDictGroupKeyWithDictKeyWithMap(dbDataDictList);
            // end 查询数据字典信息

            String sbAllUserCode = "";

            for (HseMeetingUser dbHseMeetingUser : dbHseMeetingUserList) {
                sbAllUserCode += "," + dbHseMeetingUser.getMeetingUser();
            }

            sbAllUserCode = sbAllUserCode.substring(1);

            HseMeetingInfo dbHseMeetingInfo = hseMeetingInfoMapper.selectById(reqHseMeetingInfoId);
            String dbHseMeetingInfoId = dbHseMeetingInfo.getId();
            String dbHseMeetingInfoTrial = dbHseMeetingInfo.getTrial();
            Date dbHseMeetingInfoMeetingStartTime = dbHseMeetingInfo.getMeetingStartTime();
            Date dbHseMeetingInfoMeetingEndTime = dbHseMeetingInfo.getMeetingEndTime();
            String dbHseMeetingInfoLeadingUser = dbHseMeetingInfo.getLeadingUser();
            String dbHseMeetingInfoLeadingUserName = dbHseMeetingInfo.getLeadingUserName();
            Integer dbHseMeetingInfoMeetingType = dbHseMeetingInfo.getMeetingType();
            String dbHseMeetingInfoTeamSafetyUserName = dbHseMeetingInfo.getTeamSafetyUserName();

            DataDict usedDataDict = DataDictUtil.getDataDict(
                    usedDictGroupKeyWithDictKeyWithMap
                    , DataDictUtil.DICT_GROUP_KEY_WITH_HSEMEETINGINFO_MEETING_TYPE
                    , NumberUtil.formatIntegerToString(dbHseMeetingInfoMeetingType)
            );

            String usedHseMeetingInfoMeetingType = DataDictUtil.getDictText(usedDataDict);

            // begin 获取短信信息
            SimpleDateFormat sdfYyyyMmDd = new SimpleDateFormat("yyyy/MM/dd");
            SimpleDateFormat sdfYyyyMmDdHhMm = new SimpleDateFormat("yyyy/MM/dd HH:mm");

            String strUsedHseMeetingInfoMeetingStartTimeYyyyMmDd = sdfYyyyMmDd.format(dbHseMeetingInfoMeetingStartTime) + " ";
            String strUsedHseMeetingInfoMeetingStartTime = sdfYyyyMmDdHhMm.format(dbHseMeetingInfoMeetingStartTime);
            String strUsedHseMeetingInfoMeetingEndTime = sdfYyyyMmDdHhMm.format(dbHseMeetingInfoMeetingEndTime);

            // 【会议通知】会议主题：$(title)，会议类型：，会议时间：$(meetingTime)，召开人：$(convener)，安全员：，复制信息并进入app加入会议：$(meetingAddress)

            String smsInfo = "【会议通知】会议主题：" + StringUtil.formatStringToLen0(dbHseMeetingInfoTrial)
                    + "，会议类型：" + StringUtil.formatStringToLen0(usedHseMeetingInfoMeetingType)
                    + "，会议时间：" + strUsedHseMeetingInfoMeetingStartTime + "-"
                    + (strUsedHseMeetingInfoMeetingEndTime.startsWith(strUsedHseMeetingInfoMeetingStartTimeYyyyMmDd)
                    ? strUsedHseMeetingInfoMeetingEndTime.substring(strUsedHseMeetingInfoMeetingStartTimeYyyyMmDd.length())
                    : strUsedHseMeetingInfoMeetingEndTime)
                    + "，召开人：" + StringUtil.formatStringToLen0(dbHseMeetingInfoLeadingUserName)
                    + "，负责人：" + StringUtil.formatStringToLen0(dbHseMeetingInfoLeadingUserName)
                    + "，安全员：" + StringUtil.formatStringToLen0(dbHseMeetingInfoTeamSafetyUserName)
                    + "，复制信息并进入app加入会议："
                    + "!@#$(" + dbHseMeetingInfoId + ")"
                    + "。";

            ScpCommonSmsInfo usedScpCommonSmsInfo = new ScpCommonSmsInfo();
            usedScpCommonSmsInfo.setId(IDHelper.uuidNew());
            usedScpCommonSmsInfo.setAppId(aepProperties.getAppId());
            usedScpCommonSmsInfo.setAppName(aepProperties.getAppName());
            usedScpCommonSmsInfo.setContent(smsInfo);
            usedScpCommonSmsInfo.setStaffNos(sbAllUserCode.toString());
            usedScpCommonSmsInfo.setRequestStaffNo(dbHseMeetingInfoLeadingUser);

            scpCommonSmsInfoService.save(usedScpCommonSmsInfo);
            // end 获取短信信息

            HseMeetingUser usedHseMeetingUser = new HseMeetingUser();
            usedHseMeetingUser.setSmsSendStatus(HseMeetingUser.SMSSENDSTATUS_1);

            int hseMeetingUserUpdateRows = hseMeetingUserMapper.update(usedHseMeetingUser, queryWrapperWithHseMeetingUser);

            if (hseMeetingUserUpdateRows != dbHseMeetingUserListSize) {
                throw new ScpException("hseMeetingUserUpdateRows != dbHseMeetingUserListSize");
            }

            return usedScpCommonSmsInfo;
        } catch (Exception e) {
            LOGGER.error("{}error;", logInfo, e);
            throw e;
        }
    }

    /**
     * 校验登录人是否有权限操作会议；<br/>
     * 权限主要包括：开始会议；结束会议；取消会议；修改会议；<br/>
     * 不包括：每个参会人员的签到；<br/>
     *
     * @param logInfo          logInfo
     * @param loginUserInfo    登录人信息
     * @param hseMeetingInfoId Hse会议id
     * @return 值true有权限操作；false无权限操作；
     * @throws ScpException ScpException
     */
    @Transactional(rollbackFor = Exception.class)
    protected boolean checkCanOperateMeetingInfo(final String logInfo, UserInfo loginUserInfo, String hseMeetingInfoId) throws ScpException {
        if (loginUserInfo == null
                || StringUtil.isNullOrSpace(hseMeetingInfoId)
        ) {
            LOGGER.error("{}checkCanOperateMeetingInfo;loginUserInfo or hseMeetingInfoId is null;", logInfo);
            // throw new ScpException("HseMeetingInfo: Request parameter error");
            return false;
        }

        String loginUserInfoUserId = loginUserInfo.getUserId();
        String loginUserInfoUserName = loginUserInfo.getUserName();

        LOGGER.info("{}checkCanOperateMeetingInfo.printInfo;"
                        + "hseMeetingInfoId:{};"
                        + "loginUserInfoUserId:{};loginUserInfoUserName:{};"
                , logInfo
                , hseMeetingInfoId
                , loginUserInfoUserId, loginUserInfoUserName
        );

        List<HseMeetingUser> dbHseMeetingUserList = hseMeetingUserService.loadByMeetingInfoIdAndUserId(hseMeetingInfoId, loginUserInfoUserId);

        if (ListUtil.getListSizeWith0(dbHseMeetingUserList) <= 0) {
            LOGGER.error("{}checkCanOperateMeetingInfo;无权限操作会议信息；", logInfo);
            // throw new ScpException("无权限操作会议信息");
            return false;
        }

        boolean canOperate = false;
        // meeting_user_type 参会人员类型；值1为与会人员；2为负责人；3为班组安全员；4为创建人；
        // 只有2负责人；3班组安全员；4创建人；能操作会议；
        List<Integer> canUserTypeList = Arrays.asList(
                HseMeetingUser.MEETINGUSERTYPE_2_LEADING,
                HseMeetingUser.MEETINGUSERTYPE_3_TEAM_SAFETY,
                HseMeetingUser.MEETINGUSERTYPE_4_CREATE
        );

        for (HseMeetingUser dbHseMeetingUser : dbHseMeetingUserList) {
            if (canUserTypeList.contains(dbHseMeetingUser.getMeetingUserType())) {
                canOperate = true;
                break;
            }
        }

        if (canOperate) {
            LOGGER.info("{}checkCanOperateMeetingInfo;能操作会议", logInfo);
            return true;
        }

        // throw new ScpException("无权限操作会议信息");
        return false;
    }

}
